<?php

namespace App\Http\Controllers\Admin;

use App\Enums\ResponseEnum;
use App\Http\Controllers\AdminController;
use App\Models\Content\Files;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class UploadController extends AdminController
{
    public function uploadFile(Request $request)
    {
        $request->validate(['file' => 'required|file']);
        $file = $request->file('file');
        //检查文件是否上传完成`
        if ($file->isValid()) {
            return $this->putFiles([
                'groupId' => $request->get('groupId'),
                'fileType' => $file->getMimeType(),
                'fileSize' => $file->getSize(),
                'fileName' => $file->getClientOriginalName(),
            ], $file);
        }
        return $this->error(ResponseEnum::SYSTEM_ERROR, $file->getErrorMessage());
    }

    public function networkImage(Request $request)
    {
        $request->validate(['url' => 'required|active_url']);
        $url = $request->get('url');
        try {
            $client = new \GuzzleHttp\Client(['verify' => false]);
            $resp = $client->get($url);
            abort_if($resp->getStatusCode() !== 200, ResponseEnum::UPLOAD_NETWORK_FILE_IS_NOT_ERROR);
            $contentType = $resp->getHeader('content-type')[0];
            abort_if(!str_starts_with($contentType, "image"), ResponseEnum::UPLOAD_NETWORK_FILE_FORMAT_ERROR);
            return $this->putFiles([
                'groupId' => $request->get('groupId'),
                'fileType' => $contentType,
                'fileSize' => $resp->getHeader('Content-Length')[0],
                'fileName' => pathinfo(urldecode($url))['basename'],
            ], $resp->getBody()->getContents(), true);
        }catch (\GuzzleHttp\Exception\GuzzleException $e) {
            report($e);
        }
        return $this->error(ResponseEnum::SYSTEM_ERROR);
    }

    /**
     * @param $fileData
     * @param $fileContent
     * @param bool $isNetwork
     * @return \Illuminate\Http\JsonResponse
     */
    private function putFiles($fileData, $fileContent, bool $isNetwork = false)
    {
        $fileType = $this->filesConfig($fileData["fileType"]);
        abort_if(!in_array($fileType['ext'], $fileType["extensions"], true), ResponseEnum::UPLOAD_FILE_FORMAT_ERROR, '仅支持 '.implode(',', $fileType["extensions"]).' 格式');
        abort_if($fileData['fileSize'] > $fileType["maxSize"]*1024*1024, ResponseEnum::UPLOAD_FILE_MAXSIZE_ERROR, '上传文件大小限制 '.$fileType["maxSize"].'M');
        $disk = $this->libFileSystem($fileType['storage'])->getDisk();
        $newPath = $fileType['type'].'s/'.date('Ymd');
        $isNetwork && $newPath .= '/'.Str::random(40).".".$fileType['ext'];
        if ($path = $disk->put($newPath, $fileContent)) {
            $imgPath = $isNetwork ? $newPath : $path;
            $attachment = $this->createFile([
                "user_id" => $this->guard()->id(),
                "group_id" => (int)$fileData['groupId'],
                "file_name" => $fileData['fileName'],
                "path" => $imgPath,
                "suffix" => $fileType['ext'],
                "type" => $fileData['fileType'],
                "storage" => $fileType['storage'],
                "size" => $fileData['fileSize'],
            ]);
            return $this->succeed([
                'id' => $attachment['id'],
                'fileName' => $fileData['fileName'],
                'src' =>  $disk->url($imgPath),
                'path' => $imgPath,
            ]);
        }
        return $this->error(ResponseEnum::UPLOAD_FILE_ERROR);
    }

    /**
     * @param array $fileData
     * @return array|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
     */
    private function createFile(array $fileData)
    {
        if (!empty($fileData)) {
            DB::beginTransaction();
            try {
                $model = Files::query()->create($fileData);
                $this->createSyslog('添加了一条附件记录', $fileData, $model);
                DB::commit();
                return $model;
            } catch (\Exception $e) {
                report($e);
                DB::rollBack();
            }
        }
        return [];
    }

    /**
     * @param string $fileType
     * @return array
     */
    private function filesConfig(string $fileType): array
    {
        $config = $this->getUploadConfig();
        [$type, $ext] = explode('/', $fileType);
        $data = [
            'storage' => $config['storage'],
            'ext' => $ext,
            'type' => $type,
        ];
        if ($type == 'image') {
            $data['maxSize'] = (int)$config['image_size']/1024;
            $data['extensions'] = (array)$config['image_type'];
            return $data;
        }
        $data['maxSize'] = (int)$config['file_size']/1024;
        $data['extensions'] = (array)$config['file_type'];
        return $data;
    }
}
